package com.hollycrm.hollysqm.job.tasks;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.plugin.job.type.simple.AbstractSimpleElasticJob;
import com.hollycrm.hollysqm.entities.TblQmPlan;
import com.hollycrm.hollysqm.job.tasks.dao.QmPlanJobDao;
import com.hollycrm.hollysqm.job.tasks.dao.QmPlanLogJobDao;

/**
 * 执行定时抽取计划，轮询表中的定时周期，执行当前时间点的计划
 * @author jianglong
 * @date 2017年2月23日 上午11:14:04
 */
@Service
public class TimerTasksJob extends AbstractSimpleElasticJob {
	
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private QmPlanJobDao qmPlanJobDao;
	
	@Autowired
	private QmPlanLogJobDao qmPlanLogJobDao;
	
	/**
	 * 执行质检计划的微服务调用地址
	 */
	@Value("${hollysqm.handle.planurl}")
	private String handleUrl;
	/**
	 * 计划执行时间hh:mm:ss
	 */
	@Value("${job.tasks.time}")
	private String tasksTime;

	/**
	 * Job任务主执行类，JOB定时调用本方法
	 */
	@Override
	public void process(JobExecutionMultipleShardingContext shardingContext) {
		log.info("开始执行TimerTasksJob...");
		List<TblQmPlan> planList = qmPlanJobDao.getTblQmPlanList();
		//时间周期：天、月[1~31号]、年，如：day【表示一天执行一次】,1~31【数值表示每个月的第几号执行一次】，month【表示每月的1号执行一次】，year【表示每年的1号执行一次】
		String planId = "";
		String taskTimer = "";
		boolean isExecute = false;
		for (TblQmPlan qmPlan : planList){
			if ("system".equalsIgnoreCase(qmPlan.getRemark()))
				continue;
			planId = qmPlan.getPlanId();
			taskTimer = qmPlan.getTaskTimer();
			isExecute=false;
			switch (taskTimer) {
			case "day":
				isExecute = isDay(planId);//天
				break;
			case "week":
				isExecute = isWeek(planId);//周
				break;
			case "month":
				isExecute = isMonth(planId);//月
				break;
			case "year":
				isExecute = isYear(planId);//年
				break;				
			default:
				isExecute = isSetDate(planId, taskTimer);//自定义1~31之间
				break;
			}
			System.out.println(qmPlan.getPlanId()+"\t"+qmPlan.getPlanName()+"\t"+isExecute);
			if (isExecute) executePlan(planId);
		}
		log.info("结束执行TimerTasksJob...");
	}
	
	/**
	 * 是否每天执行一次
	 * @param planId
	 * @return
	 */
	public boolean isDay(String planId){
		String upDay = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
		return qmPlanLogJobDao.getTblQmPlanLogCount(planId, String.format("%s %s", upDay, tasksTime))<=0?true:false;
	}

	/**
	 * 是否每周执行一次(每周周一)
	 * @param planId
	 * @return
	 */
	public boolean isWeek(String planId){
		Calendar cr = Calendar.getInstance();
		Date date = new Date();
		cr.setTime(date);
		int week = cr.get(Calendar.DAY_OF_WEEK);//默认从星期天、星期一...到星期六结束，分别为1,2,3,4,5,6,7
		if (week!=2){//2表示星期一
			return false;
		}
		String upDay = DateFormatUtils.format(date, "yyyy-MM-dd");
		return qmPlanLogJobDao.getTblQmPlanLogCount(planId, String.format("%s %s", upDay, tasksTime))<=0?true:false;	
	}
	
	/**
	 * 是否每月执行一次（每月的1号）
	 * @param planId
	 * @return
	 */
	public boolean isMonth(String planId){
		String upDay = DateFormatUtils.format(new Date(), "yyyy-MM") ;
		return qmPlanLogJobDao.getTblQmPlanLogCount(planId,String.format("%s-01 %s", upDay, tasksTime))<=0?true:false;	
	}
	
	/**
	 * 是否每年执行一次（每年的1月1号）
	 * @param planId
	 * @return
	 */
	public boolean isYear(String planId){
		String upDay = DateFormatUtils.format(new Date(), "yyyy");
		return qmPlanLogJobDao.getTblQmPlanLogCount(planId,String.format("%s-01-01 %s", upDay, tasksTime))<=0?true:false;	
	}
	
	/**
	 * 是否自定义日期执行一次（01~31号某一天）
	 * @param planId
	 * @param taskTimer
	 * @return
	 */
	public boolean isSetDate(String planId,String taskTimer){
		String upDay = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
		return upDay.endsWith(taskTimer)?true:false;
	}
	
	/**
	 * 执行计划远程调用
	 * @param palnId
	 */
	private void executePlan(String planId){
		log.info("执行远程计划，计划ID："+planId+"...");
		HttpGet get = null;
		HttpClient client = null;
		RequestConfig config = null;
		HttpResponse response = null;		
		try{
			config = RequestConfig.custom()
					.setSocketTimeout(15000)
					.setConnectTimeout(15000)
					.setConnectionRequestTimeout(15000)
					.build();
			log.info("客户端开始请求执行计划【"+ planId +"】地址：" + handleUrl+planId);
			client = HttpClients.createDefault();
			get = new HttpGet(handleUrl+planId);
			get.setConfig(config);
			response = client.execute(get);
			log.info("已获取服务端响应数据：" + EntityUtils.toString(response.getEntity(), "UTF-8"));		
		}catch(Exception e){
			e.printStackTrace();
			log.error("执行远程计划异常，计划ID："+planId+"...",e);
		}finally{
			log.info("客户端结束计划【"+ planId +"】执行请求完毕...");			
		}
		this.isPolling(planId);		
	}
	
	/**
	 * 判断计划是否执行完毕，则执行下一个计划;
	 * @param planId
	 */
	public void isPolling(String planId){
		long timeout = 1000*60*30;//超过30分钟则默认跳出，发送下一个计划；
		long startTime = System.currentTimeMillis();
		while (true){
			try{
				Thread.sleep(1000*30);//暂停30秒
			}catch(Exception e){
			}
			if (qmPlanLogJobDao.getQmPlanLog(planId)==null || 
					(System.currentTimeMillis()-startTime)>timeout){
				break;
			}
		}
	}
	
}
